﻿// demon10-内存管理-1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//new的使用
//使用堆区的内存有四个步骤：
//1）声明一个指针；
//2）用 new 运算符向系统申请一块内存，让指针指向这块内存；
//3）通过对指针解引用的方法，像使用变量一样使用这块内存；
//4）如果这块内存不用了，用 delete 运算符释放它。
//申请内存的语法：new 数据类型(初始值); // C++11 支持{}
//如果申请成功，返回一个地址；如果申请失败，返回一个空地址（暂时不考虑失败的情况）。
//释放内存的语法：delete 地址;
//释放内存不会失败（还钱不会失败）。

//注意：
// 动态分配出来的内存没有变量名，只能通过指向它的指针来操作内存中的数据。
// 如果动态分配的内存不用了，必须用 delete 释放它，否则有可能用尽系统的内存。
// 动态分配的内存生命周期与程序相同，程序退出时，如果没有释放，系统将自动回收。
// 就算指针的作用域已失效，所指向的内存也不会释放。
// 用指针跟踪已分配的内存时，不能跟丢

/*
// C语言中动态内存管理方式：malloc/calloc/realloc/free
#include <iostream>
using namespace std;

void Test_C()                 //C语言开辟空间
{
	int* ptr1 = (int*)malloc(sizeof(int) * 4);
	int* ptr2 = (int*)calloc(4, sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
	free(ptr1);
	free(ptr3);
}

void Test_Cplusplus()          //new/delete操作内置类型
{
	int* p1 = new int;                           
	int* p2 = new int(10);                                //开辟一个int类型对象，初始化为10
	int* p3 = new int[10] {0,1,2,3,4,5,6,7,8,9};          //开辟10个int类型,初始化为 0 1 2 3 4 5 6 7 8 9

	delete p1;
	delete p2;
	delete[]p3;
}
int main()
{
	Test_C();
	Test_Cplusplus();
}
*/

//c++写链表结点

/*
#include<iostream>
using namespace std;

struct ListNode
{
	ListNode* _next;
	int _val;
	ListNode(int val)              //初始化列表
		:_next(nullptr)
		,_val(val)
	{}
};

ListNode* CreateNode(int n)
{
	ListNode head(-1);
	ListNode* tail = &head;
	int val;
	cout << "请依次输入"<< n <<"个结点的值" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> val;
		tail->_next = new ListNode(val);
		tail = tail->_next;
	}
	return head._next;
}

int main()
{
	ListNode* node1 = new ListNode(1);
	ListNode* node2 = new ListNode(2);
	ListNode* node3 = new ListNode(3);
}
*/


//new和delete操作自定义类型
/*
#include<iostream>
using namespace std;
class A
{
public:
	A(int a=0)
		:_a(a)
	{	
		cout << "A(int a)->this:" << this << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A));    //不会调用构造和析构
	A* p2 = new A(1);                 //调用一次构造函数后立刻调用析构函数
	free(p1);
	delete p2;

	// 内置类型是几乎是一样的
	int* p3 = (int*)malloc(sizeof(int));
	int* p4 = new int;

	free(p3);
	delete p4;
	//上述内置类型不会去调用构造和析构
	
	A* p5 = (A*)malloc(sizeof(A) * 10);     //这里不会调用构造函数和析构函数
	A* p6 = new A[10];                      //先调用10次构造函数，再调用10次析构函数
	free(p5);
	delete[] p6;
	//在申请自定义类型的空间时，new会调用构造函数，delete会调用析构函数，而malloc与free不会。
	return 0;
}
*/

// new的底层是调用operator new,它是模拟实现malooc，所以new的底层还是malloc
// delete底层是调用operator delete,是模拟实现free,它是先调用析构，再调用operator delete释放内存,所以底层是free
 

// new一个对象后，delete该对象的类型不匹配
/*
#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)->this:" << this << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{

	int* p1 = new int[10];            //               
	delete p1;                        //实际不会造成内存泄露，注意，内存泄漏是不会报错的

	A* p2 = new A[10];          
	delete p2;                        //这里会报错，少了9次析构函数，如果把析构函数注释掉则不会崩溃
	//有析构函数，报错的原因是，释放的位置错了，并不是再开辟空间的初始位置释放
	return 0;
}

*/
// operator new 和 operator new[]的区别就是： operator new[]的底层还是operator new，而它的底层就是malloc
// 其中，operator new[]会躲开4个字节，方便析构的时候知道调用多少次析构




